#!/usr/bin/env bash

# FOLLOWING SERVICES RUN INSIDE A SINGLE DOCKER CONTAINER
# - PROXY
# - XSWITCH (1..*)
# - RECORDING CONTROLLER
# - RECORDING WORKER (1..*)

# GENERAL CONFIGS
# IMAGE_NAME="docker-registry.easemob.com/kefu/rtc-xswitch"
# IMAGE_VERSION="2.1.2"
# HOME="/data/apps/rtc"

function get_eth_address() {
    local eth_name=$1
    ifconfig ${eth_name} | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1'
}

EXTERNAL_IP=$(get_eth_address "eth1")
INTERNAL_IP=$(get_eth_address "eth0")


function exit_if_ne() {
    local actual=$1
    local expect=$2
    local what=$3
    if [[ ${actual} -ne ${expect} ]]; then
        echo "$what failed, exiting" >&2
        exit -1
    fi
}

ERROR=0
function warn_if_ne() {
    local actual=$1
    local expect=$2
    local what=$3
    if [[ ${actual} -ne ${expect} ]]; then
        echo "$what failed" >&2
        ERROR=-1
    fi
}

# PROXY CONFIGS
PROXY_HTTP_HOST="${INTERNAL_IP}"
PROXY_HTTP_PORT="2020"
PROXY_HTTP_ADDR="${PROXY_HTTP_HOST}:${PROXY_HTTP_PORT}"
PROXY_WS_ADDR="${INTERNAL_IP}:2021"

PROXY_CMD_OPT=(
    -api=${PROXY_HTTP_ADDR}
    -backend=${PROXY_WS_ADDR}
    -log-level=*=DEBUG
    -job-dir=/data/recorder/job/
)

PROXY_REGISTER_PAYLOAD=$(cat <<-EOF
{
  "ID":      "xswitch",
  "Name":    "xswitch",
  "Tags":    ["version=${IMAGE_VERSION}"],
  "Address": "${PROXY_HTTP_HOST}",
  "Port":    ${PROXY_HTTP_PORT},
  "Check":   {
    "Name":      "xswitch status check",
    "Notes":     "checks whether the /status uri is responsive",
    "HTTP":      "http://${PROXY_HTTP_ADDR}/status",
    "Interval":  "10s",
    "DeregisterCriticalServiceAfter": "1m"
  }
}
EOF
)

CONSUL_URL="http://127.0.0.1:8500"

function register_proxy() {
    echo ${PROXY_REGISTER_PAYLOAD}
    local status=$(curl --request PUT ${CONSUL_URL}/v1/agent/service/register \
        --data "${PROXY_REGISTER_PAYLOAD}" \
        --silent --output /dev/stderr --write-out "%{http_code}")
    exit_if_ne ${status} 200 "register proxy"
}

function deregister_proxy() {
    local status=$(curl --request PUT \
        ${CONSUL_URL}/v1/agent/service/deregister/xswitch \
        --data "${PROXY_REGISTER_PAYLOAD}" \
        --silent --output /dev/stderr --write-out "%{http_code}")
    warn_if_ne ${status} 200 "de-register proxy"
}

PROXY_PID=0

function start_proxy() {
    proxy ${PROXY_CMD_OPT[@]} &
    PROXY_PID=$!
    register_proxy
}

function stop_proxy() {
    stop_and_remove "${PROXY_CONTAINER_NAME}"
    warn_if_ne $? 0 "stop proxy"
}

# XSWITCH CONFIGS
XSWITCH_INSTANCES=2
XSWITCH_HTTP_PORT_START=3018
XSWITCH_UDP_PORT_START=30000
XSWITCH_UDP_PORT_COUNT_PER_INSTANCE=1000
XSWITCH_CONTAINER_NAME="xswitch"
XSWITCH_CONTAINER_OPT=(
    ${CONTAINER_OPT[@]}
    --volume=${HOME}/xswitch/:/data/
    --volume=${HOME}/recorder/:/recorder/
)

XSWITCH_CMD_OPT=(
    --log-config=/app/conf/log4cplus.properties
    --record-path=/recorder/
    --http-ip=${INTERNAL_IP}
    --media-ip=${EXTERNAL_IP}
    --ipm-ip=127.0.0.1
    --proxy-addr=${PROXY_WS_ADDR}
    --max-video-bitrate=1000
    --min-video-bitrate=50
    --enable-fec
    --experiment-esmb
    --lost-0
    --translate-fec
)

XSWITCH_PIDS=()
function start_xswitches() {
    for i in $(seq 1 $XSWITCH_INSTANCES); do
        http_port=$(expr $XSWITCH_HTTP_PORT_START + $i - 1)
        min_port=$(expr $XSWITCH_UDP_PORT_START + \( $i - 1 \) \* $XSWITCH_UDP_PORT_COUNT_PER_INSTANCE)
        max_port=$(expr $XSWITCH_UDP_PORT_START + $i \* 1000 - 1)
        echo "xswitch $i: http-port=$http_port media-port=$min_port-$max_port"
        rtc-xswitch ${XSWITCH_CMD_OPT[@]} \
            --http-port $http_port \
            --min-port $min_port \
            --max-port $max_port &
        XSWITCH_PIDS+=$!
    done
}

function stop_xswitches() {
    stop_and_remove ${XSWITCH_CONTAINER_NAME}
}

# RECORDER CONTROLLER
RECORDER_CONTROLLER_HTTP_ADDR="${INTERNAL_IP}:10001"
RECORDER_CONTROLLER_CONTAINER_NAME="recorder-controller"
RECORDER_CONTROLLER_CONTAINER_OPT=(
    ${CONTAINER_OPT[@]}
    --name=${RECORDER_CONTROLLER_CONTAINER_NAME}
    --volume=${HOME}/recorder/:/data/
)
RECORDER_CONTROLLER_CMD_OPT=(
    -listen=${RECORDER_CONTROLLER_HTTP_ADDR}
    -home="/data/"
    -keep=10
    -id=${RECORDER_CONTROLLER_CONTAINER_NAME}
)

function start_recording_controller() {
    docker run ${RECORDER_CONTROLLER_CONTAINER_OPT} "$IMAGE_NAME:$IMAGE_VERSION" \
        recorder ${RECORDER_CONTROLLER_CMD_OPT[@]}
    exit_if_ne $? 0 "start recording controller"
}

function stop_recording_controller() {
    stop_and_remove ${RECORDER_CONTROLLER_CONTAINER_NAME}
}

# RECORDER WORKER
RECORDER_WORKER_INSTANCES=4
RECORDER_WORKER_CONTAINER_NAME="recorder-worker"
RECORDER_WORKER_CONTAINER_OPT=(
    ${CONTAINER_OPT[@]}
    --name=${RECORDER_WORKER_CONTAINER_NAME}
    --volume=${HOME}/recorder/:/data/
)
RECORDER_WORKER_CMD_OPT=(
    -connect=${RECORDER_CONTROLLER_HTTP_ADDR}
    -home="/data/"
    -keep=10
)

function start_recording_workers() {
    for (( i=1;i<=${RECORDER_WORKER_INSTANCES};i++ )); do
        docker run ${RECORDER_WORKER_CONTAINER_OPT[@]} \
            --name="${RECORDER_WORKER_CONTAINER_NAME}-$i" \
            "$IMAGE_NAME:$IMAGE_VERSION" \
            recorder ${RECORDER_WORKER_CMD_OPT} \
            -id="${RECORDER_WORKER_CONTAINER_NAME}-$i"
        exit_if_ne $? 0 "start recording worker $i"
    done
}

function stop_recording_workers() {
    stop_and_remove ${RECORDER_WORKER_CONTAINER_NAME}
}

function logs() {
  local containers=$(docker ps --format "{{.Names}}" -q)
  echo "please select container"
  select container in ${containers[@]}
  do
    docker logs $container $@
  done
}

function start_all() {
    start_proxy
    start_xswitches
    start_recording_controller
    start_recording_workers
}

function stop_all() {
    stop_recording_workers
    stop_recording_controller
    stop_xswitches
    stop_proxy
}


function init() {
    case $1 in
        start)
          shift 1
          start_all
          ;;
        stop)
          shift 1
          stop_all
          ;;
        restart)
          shift 1
          stop_all
          start_all
          ;;
        register)
          register_proxy
          ;;
        deregister)
          deregister_proxy
          ;;
        logs)
          shift 1
          logs $@
          ;;
        *)
          start_all
          ping 127.0.0.1
          ;;
    esac
}

echo "INTERNAL_IP=${INTERNAL_IP}"
echo "EXTERNAL_IP=${EXTERNAL_IP}"

init